/**
 * @file file.c
 */

#include <string.h>
#include <stdlib.h>

#include <glib.h>

#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "file.h"
#include "common.h"

int file_is_available(Node *node, const char *file, unsigned int *size)
{
	int fd;
	int ret = P2P_OK;
	struct stat buf;

	*size = 0;
	verbose(node, VSYSCL, "open(\"%s\")\n", file);
	fd = open(file, O_RDONLY);
	if(fd == -1) {
		ret = P2P_ERROR;
		switch(errno) {
		case EACCES:
			*size = P2P_FORBIDDEN;
			break;
		case ENAMETOOLONG:
			*size = P2P_REQUEST_URI_TOO_LONG;
			break;
		case ENOENT:
			*size = P2P_NOT_FOUND;
			break;
		case ENOTDIR:
			*size = P2P_BAD_REQUEST;
			break;
		default:
			*size = P2P_INTERNAL_SERVER_ERROR;
			break;
		}
	} else {
		if(stat(file, &buf)) {
			ret = P2P_ERROR;
			switch(errno) {
			case EACCES:
				*size = P2P_FORBIDDEN;
				break;
			case ENAMETOOLONG:
				*size = P2P_REQUEST_URI_TOO_LONG;
				break;
			case ENOENT:
				*size = P2P_NOT_FOUND;
				break;
			case ENOTDIR:
				*size = P2P_BAD_REQUEST;
				break;
			default:
				*size = P2P_INTERNAL_SERVER_ERROR;
				break;
			}
		} else *size = buf.st_size;
		close(fd);
	}

	return ret;
}

int file_get_chunk(Node *node, const char *file, int start, int end, char *data)
{
	int size;
	FILE *stream;

	size = end-start+1; //FIXME: start < end?
	if(start < 0 || size < 1)
		return P2P_ERROR;

	verbose(node, VSYSCL, "fopen(\"%s\", \"r+b\")\n", file);
	if((stream = fopen(file, "r+b")) == NULL)
		return P2P_ERROR;
	verbose(node, VSYSCL, "fopen OK\n");

	/*
	verbose(node, VSYSCL, "malloc(%d)\n", size);
	if((*data = (char *)malloc(size)) == NULL) {
		fclose(stream);
		return P2P_ERROR;
	}
	verbose(node, VSYSCL, "malloc OK\n");
	*/

	fseek(stream, start, SEEK_SET); //FIXME: did it work?
	fread(data, 1, size, stream); //FIXME: how much did we really read?
	fclose(stream);

	return P2P_OK;
}

int file_set_chunk(Node *node, const char *file, int start, int end, const char *data)
{
	/*
	FILE *stream;

	verbose(node, VSYSCL, "fopen(\"%s\", \"a\")\n", file);
	if((stream = fopen(file, "a")) == NULL) {
		perror("fopen");
		return P2P_ERROR;
	}

	if(fseek(stream, start, SEEK_SET)) {
		perror("fseek");
		fclose(stream);
		return P2P_ERROR;
	}
	if(fwrite(data, 1, end-start+1, stream) != end-start+1) {
		perror("fwrite");
		fclose(stream);
		return P2P_ERROR;
	}
	fclose(stream);
	
	return P2P_OK;
	*/


	//FIXME clean up the mess
	int fd;

	verbose(node, VSYSCL, "open(\"%s\")\n", file);
	// User's umask should enforce appropriate permissions
	if((fd = open(file, O_CREAT|O_WRONLY, 0666)) == -1) {
		perror("open");
		return P2P_ERROR;
	}
	verbose(node, VSYSCL, "lseek()\n");
	if(lseek(fd, start, SEEK_SET) == -1) {
		perror("lseek");
		close(fd);
		return P2P_ERROR;
	}
	write(fd, data, end-start+1);
	close(fd);
	return P2P_OK;
}

char *complete_path(Node *node, const char *file)
{
	char *filename = NULL;
	char *fullpath = NULL;

	if((filename = strrchr(file, G_DIR_SEPARATOR)) == NULL)
		filename = (char *)file;
	else ++filename; // skip the last '/'

	fullpath = (char *)malloc(strlen(node->dir_name)+1+strlen(filename)+1);
	sprintf(fullpath, "%s%c%s", node->dir_name, G_DIR_SEPARATOR, filename);

	return fullpath;
}
